package com.itheima.java.ai.langchin4j.service;

import com.itheima.java.ai.langchin4j.enums.PromptScenario;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;

import jakarta.annotation.PostConstruct;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 提示词模板管理服务
 * 负责加载、缓存和动态生成不同场景的提示词模板
 */
@Service
@Slf4j
public class PromptTemplateService {
    
    /**
     * 提示词模板缓存
     */
    private final Map<PromptScenario, String> templateCache = new ConcurrentHashMap<>();
    
    /**
     * 模板变量替换缓存
     */
    private final Map<String, String> variableCache = new ConcurrentHashMap<>();
    
    /**
     * 初始化加载所有提示词模板
     */
    @PostConstruct
    public void initTemplates() {
        log.info("开始初始化提示词模板...");
        
        for (PromptScenario scenario : PromptScenario.values()) {
            try {
                String template = loadTemplateFromResource(scenario.getTemplateFile());
                templateCache.put(scenario, template);
                log.info("成功加载提示词模板: {} - {}", scenario.getDescription(), scenario.getTemplateFile());
            } catch (Exception e) {
                log.warn("加载提示词模板失败: {} - {}, 错误: {}", scenario.getDescription(), scenario.getTemplateFile(), e.getMessage());
                // 如果特定场景模板加载失败，使用默认模板
                if (scenario != PromptScenario.DEFAULT) {
                    try {
                        String defaultTemplate = loadTemplateFromResource(PromptScenario.DEFAULT.getTemplateFile());
                        templateCache.put(scenario, defaultTemplate);
                        log.info("为场景 {} 使用默认模板", scenario.getDescription());
                    } catch (Exception defaultError) {
                        log.error("加载默认模板也失败: {}", defaultError.getMessage());
                    }
                }
            }
        }
        
        log.info("提示词模板初始化完成，共加载 {} 个模板", templateCache.size());
    }
    
    /**
     * 从资源文件加载模板内容
     */
    private String loadTemplateFromResource(String templateFile) throws IOException {
        ClassPathResource resource = new ClassPathResource(templateFile);
        if (!resource.exists()) {
            throw new IOException("模板文件不存在: " + templateFile);
        }
        
        return StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
    }
    
    /**
     * 根据场景获取提示词模板
     */
    public String getTemplate(PromptScenario scenario) {
        String template = templateCache.get(scenario);
        if (template == null) {
            log.warn("未找到场景 {} 的模板，使用默认模板", scenario.getDescription());
            template = templateCache.get(PromptScenario.DEFAULT);
        }
        
        if (template == null) {
            log.error("连默认模板都未找到，返回基础模板");
            return getBasicTemplate();
        }
        
        return template;
    }
    
    /**
     * 根据用户消息智能选择并生成提示词
     */
    public String generatePrompt(String userMessage) {
        // 智能识别场景
        PromptScenario scenario = PromptScenario.detectScenario(userMessage);
        log.debug("为用户消息识别到场景: {}", scenario.getDescription());
        
        // 获取对应模板
        String template = getTemplate(scenario);
        
        // 动态替换变量
        return replaceVariables(template, scenario, userMessage);
    }
    
    /**
     * 根据指定场景生成提示词
     */
    public String generatePromptForScenario(PromptScenario scenario, String userMessage) {
        log.debug("为指定场景生成提示词: {}", scenario.getDescription());
        
        // 获取对应模板
        String template = getTemplate(scenario);
        
        // 动态替换变量
        return replaceVariables(template, scenario, userMessage);
    }
    
    /**
     * 替换模板中的动态变量
     */
    private String replaceVariables(String template, PromptScenario scenario, String userMessage) {
        String result = template;
        
        // 替换当前日期
        String currentDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
        result = result.replace("{{current_date}}", currentDate);
        
        // 替换当前时间
        String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm"));
        result = result.replace("{{current_time}}", currentTime);
        
        // 根据场景添加特定的上下文信息
        result = addScenarioContext(result, scenario, userMessage);
        
        return result;
    }
    
    /**
     * 根据场景添加特定的上下文信息
     */
    private String addScenarioContext(String template, PromptScenario scenario, String userMessage) {
        StringBuilder contextBuilder = new StringBuilder();
        
        switch (scenario) {
            case EMERGENCY_HANDLING:
                contextBuilder.append("\n\n## 紧急情况处理模式\n")
                    .append("- 当前处于紧急情况处理模式\n")
                    .append("- 优先考虑患者安全，必要时建议立即就医\n")
                    .append("- 提供简洁明确的应急指导\n");
                break;
                
            case APPOINTMENT_BOOKING:
                contextBuilder.append("\n\n## 预约挂号模式\n")
                    .append("- 当前处于预约挂号模式\n")
                    .append("- 需要收集完整的预约信息（姓名、身份证、科室、日期、时段）\n")
                    .append("- 提供科室推荐和医生建议\n");
                break;
                
            case MEDICATION_GUIDANCE:
                contextBuilder.append("\n\n## 用药指导模式\n")
                    .append("- 当前处于用药指导模式\n")
                    .append("- 重点关注用药安全和禁忌症\n")
                    .append("- 提供详细的用药说明和注意事项\n");
                break;
                
            case SYMPTOM_ANALYSIS:
                contextBuilder.append("\n\n## 症状分析模式\n")
                    .append("- 当前处于症状分析模式\n")
                    .append("- 采用分层诊断思维进行症状分析\n")
                    .append("- 评估症状严重程度和紧急性\n");
                break;
                
            case HEALTH_CONSULTATION:
                contextBuilder.append("\n\n## 健康咨询模式\n")
                    .append("- 当前处于健康咨询模式\n")
                    .append("- 提供预防性健康建议\n")
                    .append("- 关注生活方式和健康管理\n");
                break;
                
            case MEDICAL_CONSULTATION:
                contextBuilder.append("\n\n## 医疗咨询模式\n")
                    .append("- 当前处于医疗咨询模式\n")
                    .append("- 提供专业的医疗建议和诊疗指导\n")
                    .append("- 基于循证医学提供建议\n");
                break;
                
            default:
                // 默认场景不添加额外上下文
                break;
        }
        
        String context = contextBuilder.toString();
        if (!context.isEmpty()) {
            // 在模板末尾添加场景上下文
            return template + context;
        }
        
        return template;
    }
    
    /**
     * 获取基础模板（当所有模板都加载失败时使用）
     */
    private String getBasicTemplate() {
        return "# Role: 智能医疗客服助理\n\n" +
               "## Profile\n" +
               "- language: 中文\n" +
               "- description: 北京协和医院官方AI助手，提供专业医疗咨询及智慧就诊全流程服务\n" +
               "- personality: 耐心细致/亲切友好/专业严谨/表达简洁\n\n" +
               "## Rules\n" +
               "1. 提供专业、准确的医疗建议\n" +
               "2. 遇到紧急情况时建议立即就医\n" +
               "3. 保持友好、专业的服务态度\n" +
               "4. 今日日期：{{current_date}}\n\n" +
               "## Initialization\n" +
               "作为小智医疗助手，你必须遵守上述Rules，为用户提供专业的医疗服务。";
    }
    
    /**
     * 重新加载指定场景的模板
     */
    public boolean reloadTemplate(PromptScenario scenario) {
        try {
            String template = loadTemplateFromResource(scenario.getTemplateFile());
            templateCache.put(scenario, template);
            log.info("成功重新加载提示词模板: {}", scenario.getDescription());
            return true;
        } catch (Exception e) {
            log.error("重新加载提示词模板失败: {}, 错误: {}", scenario.getDescription(), e.getMessage());
            return false;
        }
    }
    
    /**
     * 获取所有已加载的模板信息
     */
    public Map<PromptScenario, String> getAllTemplates() {
        return new ConcurrentHashMap<>(templateCache);
    }
    
    /**
     * 清除模板缓存
     */
    public void clearCache() {
        templateCache.clear();
        variableCache.clear();
        log.info("提示词模板缓存已清除");
    }
}